{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "29e5c911-fa2d-4593-8565-3b7bb127b53d",
   "metadata": {},
   "source": [
    "# LangChain 核心模块 Agent - Self ask with search\n",
    "\n",
    "- Google 搜索对接\n",
    "    - 第三方平台：https://serpapi.com\n",
    "    - LangChain API 封装：`SerpAPIWrapper`\n",
    "- LangChain Agent 模块使用\n",
    "    - Agent 类型：`SELF_ASK_WITH_SEARCH`\n",
    "    - Agent 实例化：`initialize_agent` 方法\n",
    " \n",
    "https://python.langchain.com/docs/modules/agents/agent_types/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2866704f-c203-4c97-8221-c2ecadc52b4c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "# 更换为自己的 Serp API KEY\n",
    "os.environ[\"SERPAPI_API_KEY\"] = \"1e3c93e0753ac224098370cd71da86150c6609caba6b5aaa307e04b72a5006e1\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "add0b59e-9e30-41a1-9a4e-bacf8aefb3e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain import OpenAI, SerpAPIWrapper\n",
    "from langchain.agents import initialize_agent, AgentType, Tool\n",
    "\n",
    "llm = OpenAI(temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7047f1b0-a29c-497e-badc-d02fbcbf4082",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实例化查询工具\n",
    "search = SerpAPIWrapper()\n",
    "tools = [\n",
    "    Tool(\n",
    "        name=\"Intermediate Answer\",\n",
    "        func=search.run,\n",
    "        description=\"useful for when you need to ask with search\",\n",
    "    )\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "08a5daa3-fc7a-4ce9-aa46-ad4a6d31be74",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实例化 SELF_ASK_WITH_SEARCH Agent\n",
    "self_ask_with_search = initialize_agent(\n",
    "    tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "508c39d7-05d9-4486-83bc-924cd6a1c499",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m Yes.\n",
      "Follow up: 什么时候举办的成都大运会？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3mFri, Jul 28, 2023, 8:00 AM – Tue, Aug 8, 2023\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mFollow up: 成都大运会是第几届大运会？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m2021年夏季世界大学生运动会（英语：2021 Summer World University Games）简称为2021年成都大运会或成都大运会，是第31届夏季世界大学生运动会，原定于2021年于中国四川省成都市举行，后因2019冠状病毒病疫情等原因二次延期，最终改至2023年7月28日至8月8日举行。\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mSo the final answer is: 第31届\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'第31届'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 实际运行 Agent，查询问题（正确）\n",
    "self_ask_with_search.run(\n",
    "    \"成都举办的大运会是第几届大运会？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "5fe1f2de-f982-4953-9e8e-7f99a8289975",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m Yes.\n",
      "Follow up: 什么是2023年大运会？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m['The 2023 FISU Summer World University Games, officially known as the 2023 Summer Universiade or the XXXII Summer World University Games, and commonly known as Yekaterinburg 2023 or Ekaterinburg 2023, ...', '2023 Summer World University Games (2023年夏季世界大学生运动会) type: Aug 8, 2023 – Aug 19, 2023.', '2023 Summer World University Games (2023年夏季世界大学生运动会) main_tab_text: Overview.', '2023 Summer World University Games (2023年夏季世界大学生运动会) kgmid: /g/11hzkdc1v8.', '2023 Summer World University Games (2023年夏季世界大学生运动会) dates: Aug 8, 2023 – Aug 19, 2023.', '2023 Summer World University Games (2023年夏季世界大学生运动会) location: Yekaterinburg.', '2023 Summer World University Games (2023年夏季世界大学生运动会) main_venue: Ekaterinburg Arena (opening/closing ceremonies).', '2023 Summer World University Games (2023年夏季世界大学生运动会) motto: For You.', '2023 Summer World University Games (2023年夏季世界大学生运动会) opening: 8 August (cancelled).', '2023 Summer World University Games (2023年夏季世界大学生运动会) sport: 18.', '2023年夏季世界大学生运动会（英语：XXXII 2023 Summer World University Games）简称为叶卡捷琳堡大运会，是第32届夏季世界大学生运动会。原定于2023年8月8日至19日在 ...']\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mFollow up: 2023年大运会举办地在哪里？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m2018年3月5日正式宣布普莱西德湖成为2023年冬季大运会的主办城市，国际大体联官员称这是大运会申办历史上最强有力的一次。 由于2021年冬季世界大学生运动会因2019冠状病毒病疫情而取消，将大运会会旗正式移交给普莱西德湖的仪式改在2022年1月于都灵举行。\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "So the final answer is: Yekaterinburg\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Yekaterinburg'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 实际运行 Agent，查询问题（有歧义）\n",
    "self_ask_with_search.run(\n",
    "    \"2023年大运会举办地在哪里？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e1cf918e-a58a-4790-a4c4-2109f23dd064",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "成都举办的是第十一届大运会。\n"
     ]
    }
   ],
   "source": [
    "# Reason-only 答案（错误）\n",
    "print(llm(\"成都举办的大运会是第几届大运会？\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "32021fdf-2597-4dde-a425-13650904671f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "2023年大运会将在日本东京举办。\n"
     ]
    }
   ],
   "source": [
    "# Reason-only 答案（错误）\n",
    "print(llm(\"2023年大运会举办地在哪里？\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b73c7bd9-a835-41c1-bf28-4e203c22538b",
   "metadata": {},
   "source": [
    "#### 使用 GPT-4 作为大语言模型实现更优的 ReAct 范式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "d98ba940-a6e8-477e-83a9-2e20115ff51d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "\n",
    "chat_model = ChatOpenAI(model=\"gpt-4\", temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc4347f2-4a16-4406-92c7-d2156478bb56",
   "metadata": {},
   "outputs": [],
   "source": [
    "self_ask_with_search_chat = initialize_agent(\n",
    "    tools, chat_model, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "25978771-8e69-41f2-b9e8-b287d846e1cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mYes.\n",
      "Follow up: 2023年大运会是哪个国家举办的？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m2023年冬季世界大学生运动会（英语：2023 FISU Winter World University Games），正式名称为第31届冬季世界大学生运动会，也被称为2023年普莱西德湖大冬会或者2023年世界大冬会，于2023年1月12-22日在美国纽约州埃塞克斯县的普莱西德湖举行，是大学生参与的冬季体育项目世界 ...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mSo the final answer is: 美国纽约州埃塞克斯县的普莱西德湖\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'美国纽约州埃塞克斯县的普莱西德湖'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# GPT-4 based ReAct 答案（正确）\n",
    "self_ask_with_search_chat.run(\n",
    "    \"2023年大运会举办地在哪里？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "94da622a-8bdd-4cf3-bc7a-bcfbf88c54f4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
